<?php

namespace app;

use app\libraries\utils\Util;
use app\libraries\utils\validate\ValidatesWhenResolved;
use app\libraries\utils\validate\ValidatesWhenResolvedTrait;
use think\helper\Str;
use Throwable;

// 应用请求对象类
class Request extends \think\Request implements ValidatesWhenResolved
{
    use ValidatesWhenResolvedTrait;

    /**
     * PATHINFO变量名 用于兼容模式
     * @var string
     */
    protected $varPathinfo = 'tps';

    /**
     * 前端代理服务器真实IP头
     * @var array
     */
    protected $proxyServerIpHeader = [
        'HTTP_REMOTE_ADDR',
        'X_REAL_IP',
        'HTTP_X_REAL_IP',
        'CLIENT_IP',
        'HTTP_CLIENT_IP',
        'X_CLIENT_IP',
        'HTTP_X_CLIENT_IP',
        'X_CLUSTER_CLIENT_IP',
        'HTTP_X_CLUSTER_CLIENT_IP',
        'X_FORWARDED_FOR',
        'HTTP_X_FORWARDED_FOR',
    ];

    /**
     * 验证规则，可以以action做为Key
     *
     * @var array
     * @Author YangHB
     * @DateTime 2022-07-12 09:04:35
     *
     */
    protected array $rules = [];

    /**
     * 验证失败说明
     *
     * @var array
     * @Author YangHB
     * @DateTime 2022-07-12 09:04:48
     *
     */
    protected array $msgs = [];

    /**
     * 公共验证规则
     * @var array
     */
    protected array $commonRules = [];

    /**
     * 公共规则说明
     * @var array
     */
    protected array $commonMsg = [];

    /**
     * 将所有请求数据附于对象变量
     *
     * @Author YangHB
     * @DateTime 2022-07-12 09:04:56
     *
     * @return $this
     */
    public function refreshProperty()
    {
        foreach ($this->all() as $key => $value) {
            $setMethodName = 'set' . Str::studly($key);
            if (!blank($value) && method_exists($this, $setMethodName)) {
                try {
                    $this->$setMethodName($value);
                } catch (Throwable $e) {
                    LogError('request_set_property', '初始属性信息出错', $e->getMessage(), [
                        'method' => $setMethodName,
                        'value' => $value,
                        'error' => Util::normalizeException($e),
                    ]);
                }
            }
        }
        return $this;
    }

    /**
     * 获取客户端IP地址
     * @access public
     * @return string
     */
    public function ip(): string
    {
        if (!empty($this->realIP)) {
            return $this->realIP;
        }

        $this->realIP = $this->server('REMOTE_ADDR', '');
        if (empty($this->realIP)) {
            foreach ($this->proxyServerIpHeader as $headerKey) {
                $this->realIP = $this->server($headerKey);
                if (!empty($this->realIP)) {
                    break;
                }
            }
        }
        if (!$this->isValidIP($this->realIP)) {
            $this->realIP = parent::ip();
        }

        return $this->realIP;
    }
}
